﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using agsXMPP;
using agsXMPP.protocol.client;
using SkypeKit;

namespace ISIM
{
    public enum CallStatus { callUnsupported, none, ringingContact, incommingCall, isLive };

    public interface ISIMContact
    {
        string id { get; }
        string name { get; set; }
        Global.Availability availability { get; set; }
        string protocol { get; }
        string client { get; set; }
        bool isComposingMessage { get; set; }
        bool unreadedMessage { get; set; }
        object contactObject { get; }
        CallStatus callStatus { get; set; }
    }

    public class XmppContact : ISIMContact
    {
        string _identificator;
        ContactObject _contactObject;
        string _protocolName;

        public XmppContact(string jid, string name, ContactObject contactObject, string protocolName, string client, PresenceType presence = PresenceType.error)
        {
            _identificator = jid;
            this.name = name;
            availability = Global.Converter.GetContactAvailability(presence);
            _contactObject = contactObject;

            _protocolName = protocolName;
            this.client = client;
        }

        public string id
        {
            get { return _identificator; }
        }

        public string name
        {
            get;
            set;
        }

        public Global.Availability availability
        {
            get;
            set;
        }

        public object contactObject
        {
            get { return _contactObject; }
        }


        public string protocol
        {
            get { return _protocolName; }
        }

        public string client
        {
            get;
            set;
        }

        public bool isComposingMessage { get; set; }

        public bool unreadedMessage { get; set; }

        public class ContactObject
        {
            private XmppClientConnection _xmppClient;
            private string protocolName;

            public ContactObject(string protocolName)
            {
                this.protocolName = protocolName;
            }

            public XmppClientConnection xmppClient
            {
                get
                {
                    Global.OpenForms.mainForm.Invoke(new System.Windows.Forms.MethodInvoker(() =>
                    {
                        XmppClass xmpp = null;
                        if (protocolName == "facebook")
                            xmpp = Global.OpenForms.mainForm.fb;
                        if (protocolName == "gtalk")
                            xmpp = Global.OpenForms.mainForm.gt;

                        if (xmpp != null)
                            _xmppClient = xmpp.xmppClient;
                    }));

                    return _xmppClient;
                }
            }
        }


        public CallStatus callStatus
        {
            get { return CallStatus.callUnsupported; }
            set { }
        }
    }


    public class IcqContact : ISIMContact
    {
        ContactObject contactObj;

        public IcqContact(IcqSharp.Base.Contact contact)
        {
            contactObj = new ContactObject(contact);
            availability = Global.Converter.GetContactAvailability(contact.Status);
        }

        public string id
        {
            get { return contactObj.contact.Uin; }
        }

        public string name
        {
            get
            {
                if (contactObj.contact.Nickname != null)
                    return contactObj.contact.Nickname;
                else
                    return contactObj.contact.Uin;
            }
            set { }
        }

        public Global.Availability availability
        {
            get;
            set;
        }

        public object contactObject
        {
            get { return contactObj; }
        }

        public string protocol
        {
            get { return "ICQ"; }
        }

        public string client
        {
            get { return "ICQ"; }
            set { }
        }

        public bool isComposingMessage { get; set; }

        public bool unreadedMessage { get; set; }


        public class ContactObject
        {
            private IcqSharp.Session _session;
            private IcqSharp.Base.Contact _contact;

            public ContactObject(IcqSharp.Base.Contact contact)
            {
                if (contact.Nickname == null)
                    contact.Nickname = contact.Uin;

                _contact = contact;
            }

            public IcqSharp.Session session
            {
                get
                {
                    Global.OpenForms.mainForm.Invoke(new System.Windows.Forms.MethodInvoker(() =>
                    {
                        _session = Global.OpenForms.mainForm.icq.session;
                    }));

                    return _session;
                }
            }

            public IcqSharp.Base.Contact contact
            {
                get { return _contact; }
            }
        }


        public CallStatus callStatus
        {
            get { return CallStatus.callUnsupported; }
            set { }
        }
    }


    public class SkypeContact : ISIMContact
    {
        public SktContact skypeContact;
        public SktConversation conversation;
        ContactObject _contactObject;

        public SkypeContact(SktContact skypeContact, SktConversation conversation)
        {
            this.skypeContact = skypeContact;
            this.conversation = conversation;
            if ((conversation != null) && (conversation.P_TYPE != SktConversation.TYPE.DIALOG))
                availability = Global.Availability.Conference;
            else
                availability = Global.Converter.GetContactAvailability(skypeContact);
            _contactObject = new ContactObject(skypeContact, conversation);
            callStatus = CallStatus.none;
        }

        public string id
        {
            get
            {
                if ((skypeContact != null) && ((conversation == null) || (conversation.P_TYPE != SktConversation.TYPE.CONFERENCE)))
                    return skypeContact.P_SKYPENAME;
                else
                    return conversation.P_IDENTITY;
            }
        }

        public string name
        {
            get
            {
                if (skypeContact != null)
                    return skypeContact.P_DISPLAYNAME;
                else
                    return conversation.P_DISPLAYNAME;
            }
            set { }
        }

        public Global.Availability availability
        {
            get;
            set;
        }

        public object contactObject
        {
            get { return _contactObject; }
        }

        public string protocol
        {
            get { return "skype"; }
        }

        public string client
        {
            get
            { 
                if ((skypeContact != null) && (skypeContact.P_ABOUT.Contains("::ISIM::")))
                    return "::ISIM::";
                else
                    return "Skype";
            }
            set { }
        }

        public bool isComposingMessage { get; set; }

        public bool unreadedMessage { get; set; }

        public class ContactObject
        {
            private SktContact skypeContact;
            private SktConversation _conversation;
            SktSkype skypeInstance;

            public ContactObject(SktContact skypeContact, SktConversation conversation)
            {
                this.skypeContact = skypeContact;
                _conversation = conversation;
            }

            public SktContact contact
            {
                get { return skypeContact; }
            }

            public SktConversation conversation
            {
                get
                {
                    if (_conversation == null)
                        return skypeContact.OpenConversation();
                    else
                        return _conversation;
                }
            }

            public SktSkype skype
            {
                get
                {
                    Global.OpenForms.mainForm.Invoke(new System.Windows.Forms.MethodInvoker(() =>
                    {
                        skypeInstance = Global.OpenForms.mainForm.skype.GetSkypeInstance();
                    }));
                    return skypeInstance;
                }
            }
        }


        public CallStatus callStatus
        {
            get;
            set;
        }
    }


    /// <summary>
    /// Porovnává nejdřív podle dostupnosti a pak podle jména. Jednoduše přičte ke jménu dostupnost a porovná -> 1David. Je to do 6tky takže neřešim :P
    /// </summary>
    public class ISIMcontactComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            int result = -1;
            try
            {
                string c1 = (int)(x as ContactListViewItem).contact.availability + Global.Converter.GetRenamedContactName((x as ContactListViewItem).contact);
                string c2 = (int)(y as ContactListViewItem).contact.availability + Global.Converter.GetRenamedContactName((y as ContactListViewItem).contact);

                result = string.Compare(c1, c2);
            }
            catch (NullReferenceException)
            {
                result = -1;
            }
            return result;
        }
    }
}
